package servlet;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.FieldPosition;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileItemFactory;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;

import service.JobService;
import service.MovieService;
import util.PhysicalFeature;
import util.PhysicalFeature.*;
import util.ExpindConstants;
import util.PhysicalFeatureUtil;
import util.RegexUtil;
import util.Title;
import util.TitleUtil;

import domain.ActorJob;
import domain.CrewJob;
import domain.Movie;
import domain.User;
import ex.DatabaseException;
import ex.ProjectCompositionFailedException;

public class CreateProject extends HttpServlet {
	
	MovieService mService=new MovieService();
	JobService jService=new JobService();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		HttpSession session=request.getSession();
		try{			
			if(session.getAttribute("user")!=null){
				User user=(User) session.getAttribute("user");
				if(user!=null)
				{
					List<Title> titles= TitleUtil.getTitles();
					request.setAttribute("titles", titles);
					
					RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/user/create-project.jsp");
					if (dispatcher != null) dispatcher.forward(request, response);
				}
				else {
					response.sendRedirect("home");
				}
			}
			else {
				response.sendRedirect("home");
			}
		}
		catch (Exception e) {
			// TODO: handle exception
		}		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try{
			request.setCharacterEncoding("UTF-8");
			List<Title> titlesAll= TitleUtil.getTitles();
			request.setAttribute("titles", titlesAll);
			
			HttpSession session=request.getSession();
						
			if(session.getAttribute("user")!=null){
				User user=(User) session.getAttribute("user");
				if(user!=null)
				{
					// Create a factory for disk-based file items
					FileItemFactory factory = new DiskFileItemFactory();
					// Create a new file upload handler
					ServletFileUpload upload = new ServletFileUpload(factory);
					// Parse the request
					List<FileItem> items = upload.parseRequest(request); 
					Map<String, String> fieldMap = new HashMap<String, String>();
					// Process the uploaded items
					Iterator<FileItem> iter = items.iterator();
					String destination = "";
					while (iter.hasNext()) {
						FileItem item = (FileItem) iter.next();
						if(item.isFormField()){
							String value=item.getString("UTF-8").trim();
							String name=item.getFieldName();
							if(fieldMap.containsKey(name) ){
								value=value+"#" +fieldMap.get(name);
							}
							fieldMap.put(item.getFieldName(),value );
						}else{
							String fileName="/" + fieldMap.get("email") + ".jpeg";
							destination = getServletContext().getRealPath("/jsp/user/images/movie"+ fileName);
							File uploadedFile = new File(destination);
							item.write(uploadedFile);
							destination=ExpindConstants.rootPath + "/jsp/user/images/movie"+ fileName;
						}
					}
					
					
					
					String numOfActors=fieldMap.get("numofactors");
					String numOfCrews=fieldMap.get("numofcrews");
					if(!RegexUtil.isParsableToInt(numOfActors) ||!RegexUtil.isParsableToInt(numOfCrews)){
						response.sendRedirect("home");
					}
					
					String name=fieldMap.get("projectname");
					String description=fieldMap.get("description");
					String genre=fieldMap.get("genre");
					String imageURL=fieldMap.get("imageURL");
					
					Movie movie=new Movie(-1, user,name, genre, "0", description, 0, imageURL, "", 0, 0, false, /*new ArrayList<User>(), new ArrayList<User>(),new ArrayList<User>(),*/ new Timestamp((new java.util.Date()).getTime()));
					mService.createMovie(movie);
					
					Movie mo= mService.getLastAddedMovie();
					
					//number of actors
					int na=Integer.parseInt(numOfActors);
					
					//number of crews
					int nc=Integer.parseInt(numOfCrews);
					
					//actor attributes are added to the database
					for(int i=1;i<=na;i++){

						int isFemale =getGenders(i,fieldMap);
						
						String age=request.getParameter("ageAA"+i);
						if(!RegexUtil.isNullOrEmpty(age)){
							if(!RegexUtil.isParsableToInt(age)){
								throw new ProjectCompositionFailedException("Age must be an integer value!");
							}
						}
						else
							age="-1";
						
						String height =fieldMap.get("heightAA"+i);
						if(!RegexUtil.isNullOrEmpty(height)){
							if(!RegexUtil.isParsableToInt(height)){
								throw new ProjectCompositionFailedException("Height must be an integer value!");
							}
						}
						else
							height="-1";
						
						String weight =fieldMap.get("weightAA"+i);
						if(!RegexUtil.isNullOrEmpty(weight)){
							if(!RegexUtil.isParsableToInt(weight)){
								throw new ProjectCompositionFailedException("Weight must be an integer value!");
							}
						}
						else
							weight="-1";
						
						String hairString =  getHairColors(i,fieldMap);
						
						String skinString =getSkinColors(i,fieldMap);
						
						String eyesString =  getEyeColors(i,fieldMap);

						String jobDescription =fieldMap.get("descriptionAA"+i);
						String count =fieldMap.get("countAA"+i);	
						if(!RegexUtil.isParsableToInt(count)){
							throw new ProjectCompositionFailedException("Count must be an integer value!");
						}
						
						ActorJob aj = new ActorJob(-1, user.getUid(), mo.getMid(), hairString, eyesString, skinString, Integer.parseInt(height), Integer.parseInt(weight), jobDescription, Integer.parseInt(age), new Timestamp((new java.util.Date()).getTime()), isFemale, Integer.parseInt(count));
						jService.createActorJob(aj);
					}
					
					//crew attributes are added to the database
					for(int i=1;i<=nc;i++){
						String titleName=fieldMap.get("titleCC"+i);
						String jobDescription =fieldMap.get("descriptionCC"+i);
						String count =fieldMap.get("countCC"+i);
						if(!RegexUtil.isParsableToInt(count)){
							throw new ProjectCompositionFailedException("Count must be an integer value!");
						}
						Title t = TitleUtil.getTitleByTitleName(titleName);
						if (t!=null){
							CrewJob cj=new CrewJob(-1, user.getUid(), mo.getMid(), t.getTitleBit(), jobDescription, new Timestamp((new java.util.Date()).getTime()), Integer.parseInt(count));
							jService.createCrewJob(cj);
						}
					}
					response.sendRedirect("home");
				}
				else
					response.sendRedirect("home");
			}
			else {
				response.sendRedirect("home");
			}
		}
		catch (ProjectCompositionFailedException e) {
			request.setAttribute("createError", e.getMessage());
			RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/user/create-project.jsp");
			if (dispatcher != null) dispatcher.forward(request, response);
		}
		catch (DatabaseException e) {
			request.setAttribute("createError", e.getMessage());
			RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/user/create-project.jsp");
			if (dispatcher != null) dispatcher.forward(request, response);
		}
		catch (Exception e) {
			request.setAttribute("createError", "A general error occured:" + e.getMessage());
			RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/user/create-project.jsp");
			if (dispatcher != null) dispatcher.forward(request, response);
		}
	}
	
	protected String getHairColors(int order,Map<String, String> fieldMap) throws ParseException{
		String haircolorString="";
		String[] haircolors =  RegexUtil.splitDiyez(fieldMap.get("hairAA"+order));
		List<Hair> hair = new ArrayList<Hair>(); 
		if (haircolors == null || haircolors.length==0) {
			hair=PhysicalFeatureUtil.getHairs();
			Iterator<Hair> haircolorIterator = hair.iterator();
			while (haircolorIterator.hasNext()){
				haircolorString += haircolorIterator.next().getHairName()+"#";
			}
		}
		else
			for (int i = 0; i < haircolors.length; i++)	{
				String value=haircolors[i];
				haircolorString+=value+"#";
			}

		return haircolorString;
	}

	protected String getSkinColors(int order,Map<String, String> fieldMap) throws ParseException{
		String skincolorString="";
		String[] skincolors =  RegexUtil.splitDiyez(fieldMap.get("skinAA"+order));
		List<Skin> skin = new ArrayList<Skin>(); 
		if (skincolors == null || skincolors.length==0) {
			skin=PhysicalFeatureUtil.getSkins();
			Iterator<Skin> skincolorIterator = skin.iterator();
			while (skincolorIterator.hasNext()){
				skincolorString += skincolorIterator.next().getSkinName()+"#";
			}
		}
		else
			for (int i = 0; i < skincolors.length; i++)	{
				String value=skincolors[i];
				skincolorString+=value+"#";
			}

		return skincolorString;
	}
	
	protected String getEyeColors(int order,Map<String, String> fieldMap) throws ParseException{
		String eyecolorString="";
		String[] eyecolors =  RegexUtil.splitDiyez(fieldMap.get("eyesAA"+order));
		List<Eyes> eye = new ArrayList<Eyes>(); 
		if (eyecolors == null || eyecolors.length==0) {
			eye=PhysicalFeatureUtil.getEyes();
			Iterator<Eyes> eyecolorIterator = eye.iterator();
			while (eyecolorIterator.hasNext()){
				eyecolorString += eyecolorIterator.next().getEyesName()+"#";
			}
		}
		else
			for (int i = 0; i < eyecolors.length; i++)	{
				String value=eyecolors[i];
				eyecolorString+=value+"#";
			}

		return eyecolorString;
	}
	
	protected int getGenders(int order,Map<String, String> fieldMap) throws ParseException{
		String[] genders = RegexUtil.splitDiyez(fieldMap.get("genderAA"+order));
		if (genders == null || genders.length==0 || genders.length==2) {
			return 2;
		}
		else
		{
			String value=genders[0];
			if(value.equalsIgnoreCase("female")){
				return 1;
			}
			else{
				return 0;
			}
		}
	}
}
